class Datum {
    constructor (props) {
        const {data, value, valueField, textField} = props;
        this.value = value || [];
        this.valueField = valueField || 'id';
        this.textField = textField || 'text';

        this.dataMap = new Map();
        this.displayData = [];
        this.valueMap = new Map();
        this.events = {};
        this.textEvent = null;
        this.showLength = 0;
        this.headerEvent = null;
        this.multi = props.multi;
        this.setData(data);
        this.setValue(this.value);
    }

    bind (id, event) {
        this.events[id] = event;
    }

    bindText (textEvent) {
        this.textEvent = textEvent;
    }

    unbind (id) {
        delete this.events[id];
    }

    unBindText () {
        this.textEvent = null;
    }

    setValue (value) {
        this.value = value;
        if (value && value !== this.cachedValue) {
            this.initValue();
        }
    }

    getValue () {
        const value = [];
        this.valueMap.forEach((checked, id) => {
            if (checked === 1) {
                value.push(id);
            }
        });
        this.cachedValue = value;
        return value;
    }

    getText () {
        const text = [];
        this.valueMap.forEach((checked, id) => {
            if (checked === 1) {
                if (this.dataMap.get(id)) {
                    text.push(this.dataMap.get(id)[this.textField]);
                }
            }
        });
        return text;
    }

    setData (data) {
        this.orignData = data || [];
        this.dataMap = new Map();
        this.displayData = data;
        if (!data) { return; }
        this.initData(data);
        this.initValue();
    }

    initData (data) {
        const arr = [];
        data.forEach(item => {
            if (item.children && item.children.length) {
                this.showLength += item.children.length + 1;
                arr.push(item);
                item.children.forEach(child => {
                    arr.push(child);
                    this.dataMap.set(`${child[this.valueField]}`, child);
                });
            } else {
                this.showLength ++;
                arr.push(item);
                this.dataMap.set(`${item[this.valueField]}`, item);
            }
        });
        this.data = arr;
    }

    initValue () {
        if (!this.data || !this.value) { return undefined; }
        this.value.forEach(id => {
            this.setValueMap(id, 1);
        });
        if (this.textEvent) {
            this.textEvent();
        }
    }

    clear () {
        this.valueMap.clear();
        this.setValue([]);
    }

    setValueMap (id, checked) {
        if (checked) {
            this.valueMap.set(id, checked);
        } else {
            this.valueMap.delete(id);
        }
        const update = this.events[id];
        if (update) {
            update();
        }
    }

    filter (keyword) {
        const {orignData, textField} = this;
        let showLength = 0;
        const arr = [];
        orignData.forEach(item => {
            if (item.children && item.children instanceof Array) {
                let hiddenNum = 0;
                arr.push(item);
                item.children.forEach(child => {
                    child._hidden = child[textField].toLowerCase().indexOf(keyword.toLowerCase()) === -1;
                    if (child._hidden) {
                        hiddenNum ++;
                    } else {
                        showLength ++;
                        arr.push(child);
                    }
                });
                item._hidden = hiddenNum === item.children.length;
                if (!item._hidden) {
                    showLength ++;
                } else {
                    arr.pop();
                }
            } else {
                item._hidden = item[textField].toLowerCase().indexOf(keyword.toLowerCase()) === -1;
                if (!item._hidden) {
                    showLength ++;
                    arr.push(item);
                }
            }
        });
        this.showLength = showLength;
        this.data = arr;
    }

    getVisibleDataLength () {
        return this.showLength;
    }

    getChecked (id) {
        const value = this.get(id);
        let checked = value === 1;
        if (value === 2) { checked = 'indeterminate'; }
        return checked;
    }

    get (id) {
        return this.valueMap.get(id);
    }

    set (id, checked) {
        if (!this.isDisabled(id)) {
            if (this.multi) {
                this.setValueMap(id, checked);
            } else {
                const lastId = this.getValue()[0];
                this.setValueMap(lastId, 0);
                this.setValueMap(id, checked);
            }

            if (this.textEvent) {
                this.textEvent();
            }
        }
    }

    isDisabled (id) {
        const item = this.dataMap.get(id);
        if (item) { return item.disabled; }
        return false;
    }
}

export default Datum;
